"""
description:雪花算法
"""

import threading
import time


class Snowflake:
    def __init__(self, worker_id=0, datacenter_id=0):
        self.worker_id = worker_id  # 工作机器ID（0~31）
        self.datacenter_id = datacenter_id  # 数据中心ID（0~31）
        self.sequence = 0
        self.last_timestamp = -1

    def next_id(self):
        with threading.Lock():  # 线程安全
            timestamp = int(time.time() * 1000)  # 毫秒级时间戳

            if timestamp < self.last_timestamp:
                raise ValueError("时钟回拨！")

            if timestamp == self.last_timestamp:
                self.sequence = (self.sequence + 1) & 0xFFF  # 12位序列号
                if self.sequence == 0:
                    timestamp = self._wait_next_millis()
            else:
                self.sequence = 0

            self.last_timestamp = timestamp

            return ((timestamp - 1288834974657) << 22) | \
                   (self.datacenter_id << 17) | \
                   (self.worker_id << 12) | \
                   self.sequence

    def _wait_next_millis(self):
        timestamp = int(time.time() * 1000)
        while timestamp <= self.last_timestamp:
            timestamp = int(time.time() * 1000)
        return timestamp

# 全局单例
snowflake = Snowflake(worker_id=1)